package com.xxx.service.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.xxx.common.constant.JwtClaimsConstant;
import com.xxx.common.constant.UserTypeConstant;
import com.xxx.common.context.UserContextHolder;
import com.xxx.common.properties.JwtProperties;
import com.xxx.common.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.SignatureException;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.Map;

@Component
@Slf4j
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private final JwtProperties jwtProperties;
    private final JwtUtil jwtUtil;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        String path = request.getRequestURI();

        // 跳过不需要认证的路径
        if (shouldSkipAuthentication(path)) {
            filterChain.doFilter(request, response);
            return;
        }

        log.info("🔐 JWT过滤器拦截请求: {} {}", request.getMethod(), path);

        // 获取令牌
        String token = getAuthorizationHeader(request);
        if (token == null || token.isEmpty()) {
            log.warn("⚠️ 请求未携带Authorization头");
            sendError(response, "认证失败：请求未携带Authorization头");
            return;
        }
        log.info("JWT令牌: {}", token);

        try {
            Claims claims;
            Integer id = null;
            String userType = null;

            // 去除Bearer前缀
            if (token.startsWith("Bearer ")) {
                token = token.substring(7);
            }

            // 尝试解析用户令牌
            try {
                claims = jwtUtil.parseToken(token, jwtProperties.getUserSecretKey());
                id = (Integer) claims.get(JwtClaimsConstant.USER_ID);
                userType = UserTypeConstant.USER; // 使用字符串常量
                log.info("用户ID: {}", id);
            } catch (Exception e) {
                // 如果不是用户令牌，尝试解析管理员令牌
                claims = jwtUtil.parseToken(token, jwtProperties.getAdminSecretKey());
                id = (Integer) claims.get(JwtClaimsConstant.ADMIN_ID);
                userType = UserTypeConstant.ADMIN; // 使用字符串常量
                log.info("管理员ID: {}", id);
            }

            if (id == null) {
                throw new IllegalArgumentException("令牌中未包含有效ID");
            }

            // 设置用户上下文
            UserContextHolder.setCurrentId(id);
            UserContextHolder.setCurrentUserType(userType);
            log.info("✅ 已设置用户ID: {}, 类型: {}", id, userType);

            // 继续处理请求
            filterChain.doFilter(request, response);
        } catch (ExpiredJwtException e) {
            sendError(response, "令牌已过期");
        } catch (SignatureException e) {
            sendError(response, "无效的令牌签名");
        } catch (IllegalArgumentException e) {
            sendError(response, e.getMessage());
        } catch (Exception e) {
            sendError(response, "认证失败");
        } finally {
            UserContextHolder.clear();
        }
    }

    // 添加缺失的方法：获取Authorization头（兼容大小写）
    private String getAuthorizationHeader(HttpServletRequest request) {
        Enumeration<String> headers = request.getHeaderNames();
        while (headers.hasMoreElements()) {
            String name = headers.nextElement();
            if ("authorization".equalsIgnoreCase(name)) {
                return request.getHeader(name);
            }
        }
        return null;
    }

    private boolean shouldSkipAuthentication(String path) {
        // 跳过登录、登出、注册等不需要认证的端点
        return path.equals("/api/user/login") ||
                path.equals("/api/user/logout") ||
                path.equals("/api/user/register") ||
                path.equals("/api/admin/login") ||
                path.equals("/api/admin/logout") ||
                path.equals("/api/admin/register") ||
                // 公开访问的接口
                path.equals("/api/music") ||                   // 分页获取音乐列表
                path.equals("/api/user") ||                    // 用户相关公开接口
                path.startsWith("/api/genre");                 // 曲风相关公开接口

    }

    private void sendError(HttpServletResponse response, String message) throws IOException {
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());

        Map<String, Object> body = new LinkedHashMap<>();
        body.put("code", HttpServletResponse.SC_UNAUTHORIZED);
        body.put("status", "UNAUTHORIZED");
        body.put("message", message);
        body.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));

        try (PrintWriter writer = response.getWriter()) {
            new ObjectMapper().writeValue(writer, body);
        }
    }
}